home *** CD-ROM | disk | FTP | other *** search
- // Command line renderer for After Effects.
-
- // This function constructs an AECommandLineRenderer.
- // One and only one of these will be created to perform rendering tasks
- // at the end of this file.
- //
- // The constructor has 3 sections:
- // [1] define all the variable-type attributes used by this class
- // [2] define all the functions used by this class
- // [3] assign all the functions to be method-type attributes.
- function AECommandLineRenderer() {
-
- // [1] define all the variable-type attributes used by this class
- //
- // Input before parsing
- //
- this.inArgs = null;
- //
- // Input after parsing
- //
- this.in_project_path = null;
- this.in_comp_name = null;
- this.in_RStemplate = null;
- this.in_OMtemplate = null;
- this.in_output_path = null;
- this.in_logfile_path = null;
- this.in_start_frame = null;
- this.in_end_frame = null;
- this.in_image_cache_percent = null;
- this.in_max_mem_percent = null;
- this.in_verbose_flag = null;
- this.in_close_flag = null;
- this.in_sound_flag = null;
- this.in_port_address = null;
- //
- // Exit codes:
- //
- this.EXIT_OK = 0;
- this.EXIT_FAILURE_CODE_FROM_APP = 1;
- this.EXIT_SHOW_USAGE = 2;
- this.EXIT_SYNTAX_ERROR = 3;
- this.EXIT_SYNTAX_ERROR_USER_LOG = 4;
- this.EXIT_OTHER_SCRIPTING_ERROR = 5;
- this.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG = 6;
- this.EXIT_AERENDER_RUNTIME = 7;
- this.EXIT_AERENDER_RUNTIME_USER_LOG = 8;
- this.EXIT_AE_RUNTIME = 9;
- this.EXIT_AE_RUNTIME_USER_LOG = 10;
- this.EXIT_CANNOT_OPEN_SOCKET = 11;
- this.EXIT_CODE_NO_LONGER_IN_USE = 12;
- //
- // Exit code message prefixes:
- //
- this.EXIT_MSG_PREFIX = new Array(
- "", // EXIT_OK
- "ERROR: ", // EXIT_FAILURE_CODE_FROM_APP
- "USAGE: ", // EXIT_SHOW_USAGE
- "SYNTAX ERROR: ", // EXIT_SYNTAX_ERROR
- "SYNTAX ERROR: ", // EXIT_SYNTAX_ERROR_USER_LOG
- "ERROR: ", // EXIT_OTHER_SCRIPTING_ERROR
- "ERROR: ", // EXIT_OTHER_SCRIPTING_ERROR_USER_LOG
- "ERROR: ", // EXIT_AERENDER_ERROR
- "ERROR: ", // EXIT_AERENDER_ERROR_USER_LOG
- "ERROR: ", // EXIT_AE_RUNTIME
- "ERROR: ", // EXIT_AE_RUNTIME_USER_LOG
- "ERROR: ", // EXIT_CANNOT_OPEN_SOCKET
- "", // EXIT_CODE_NO_LONGER_IN_USE
- );
- //
- // Messages:
- //
- this.MSG_NONE = "";
- this.MSG_NOT_HANDLED_HERE = "reported by another script or AE runtime.";
- this.MSG_SHOW_USAGE = "";
- this.MSG_TRIED_TO_PARSE_UNDEFINED = "aerender tried to parse an undefined argument.";
- this.MSG_UNDEFINED_VALUE_FOR_FLAG = "no value given for flag: ";
- this.MSG_BAD_FLAG = "Illegal argument flag: ";
- this.MSG_NO_PROJECT = "No project provided and no project open.";
- this.MSG_BAD_VERBOSE_FLAG = "Bad value for -verbose.";
- this.MSG_BAD_CLOSE_FLAG = "Bad value for -close.";
- this.MSG_BAD_SOUND_FLAG = "Bad value for -sound.";
- this.MSG_COMP_NOT_FOUND = "No comp was found with the given name.";
- this.MSG_AE_RUNTIME = "Runtime error in After Effects.";
- this.MSG_ADDING_TO_RQ = "PROGRESS: Adding specified comp to Render Queue";
- this.MSG_NEEDS_OUTPUT = "Specified render queue item needs output file but none provided.";
- this.MSG_RS_TEMPLATE_NOT_FOUND = "No render settings template was found with the given name.";
- this.MSG_OM_TEMPLATE_NOT_FOUND = "No output module template was found with the given name.";
- this.MSG_CAN_NOT_OPEN_SOCKET = "Can not open socket.";
- this.MSG_NO_COMP_YES_TEMPLATE = "WARNING: -RStemplate argument ignored since no -comp provided.";
- this.MSG_NO_COMP_YES_OMTEMPLATE = "WARNING: -OMtemplate argument ignored since no -comp provided.";
- this.MSG_NO_COMP_YES_OUTPUT = "WARNING: -output argument ignored since no -comp provided.";
- this.MSG_NO_COMP_YES_START_OR_END = "WARNING: -s and/or -e arguments ignored since no -comp provided.";
- this.MSG_SKIPPING_WILL_CONTINUE = "INFO: Skipping render queue item with correct comp name but marked to continue from a partly complete render.";
- this.MSG_RENDER_ABORTED = "INFO: Render aborted.";
- this.MSG_LOG_DIR_NO_EXISTS = "ERROR: Directory specified for log file does not exist: ";
- this.MSG_LOG_DIR_NOT_A_DIR = "ERROR: Directory specified for log file is a file, not a directory: ";
- this.MSG_LOG_CAN_NOT_OPEN = "ERROR: Can not open log file. Try checking write protection of directory: ";
- //
- // Variables for rendering
- //
- this.log_file = null;
- this.has_user_log_file = false;
- this.is_verbose_mode = true;
- this.saved_sound_setting = null;
- this.my_sound_setting = null;
-
- // [2] define all the functions used by this class
- //
- // Report an error. This writes errors to the log file, if present.
- // This is called from the context of the application, so we
- // need to precede variable names with gAECommandLineRenderer
- //
- function my_onError(error_string, severity_string)
- {
- // This method is called with a variety of types of messages.
- // The severity_string tells us what kind.
- // Choices are:
- // NAKED, INFO, WARNING, PROBLEM, FATAL, PROGRESS, and DEBUG
-
- // Two of these, PROBLEM and FATAL, are errors that should cause us to change
- // the exit code:
- if (severity_string == "PROBLEM" || severity_string == "FATAL"){
- // These two errors cause us to change the exit code.
- // We don't write an error or throw here, because we got here as part of a thrown
- // error already, and the message will be printed as part of the catch.
- gAECommandLineRenderer.SetExitCode(gAECommandLineRenderer.EXIT_AE_RUNTIME);
- } else {
- // PROBLEM and FATAL will throw exceptions, and so will be logged to the file
- // when we catch the exception.
- // All other errors (NAKED, INFO, WARNING, PROGRESS, and DEBUG) will not
- // throw exceptions. So we log them to the file right here:
- if (gAECommandLineRenderer.is_verbose_mode) {
- if (gAECommandLineRenderer.log_file != null){
- if (severity_string == "NAKED"){
- // everybody is confused by this category. Just use INFO instead.
- gAECommandLineRenderer.log_file.writeln("INFO:" + error_string);
- } else {
- gAECommandLineRenderer.log_file.writeln(severity_string + ":" + error_string);
- }
- }
- }
- }
- // call the error handler that was in place before we started rendering.
- if (gAECommandLineRenderer.oldErrorHandler){
- gAECommandLineRenderer.oldErrorHandler(error_string,severity_string);
- }
- }
-
- // Report an error and throw an exception.
- // Causes the script to exit.
- function my_SetExitCodeAndThrowException(code, message)
- {
- this.SetExitCode(code);
- throw (this.EXIT_MSG_PREFIX[code] + message);
- }
-
- // Report an error. This establishes exitCodes for reporting errors from AfterFX.
- function my_SetExitCode(code)
- {
- // Some codes are set differently depending on whether we have a custom user
- // log file. Check for these and use the alternate if appropriate.
- var real_code = code;
- if (gAECommandLineRenderer.has_user_log_file){
- switch(real_code){
- case gAECommandLineRenderer.EXIT_SYNTAX_ERROR:
- real_code = gAECommandLineRenderer.EXIT_SYNTAX_ERROR_USER_LOG;
- break;
- case gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR:
- real_code = gAECommandLineRenderer.EXIT_OTHER_SCRIPTING_ERROR_USER_LOG;
- break;
- case gAECommandLineRenderer.EXIT_AERENDER_RUNTIME:
- real_code = gAECommandLineRenderer.EXIT_AERENDER_RUNTIME_USER_LOG;
- break;
- case gAECommandLineRenderer.EXIT_AE_RUNTIME:
- real_code = gAECommandLineRenderer.EXIT_AE_RUNTIME_USER_LOG;
- break;
- }
- }
-
- // Always keep the first error. So only set if the exitCode is still EXIT_OK.
- if (app.exitCode == gAECommandLineRenderer.EXIT_OK){
- app.exitCode = real_code;
- }
- }
-
- // Arguments may be enclosed in quotes. This
- // will remove them and return the result.
- function my_StripAnyEnclosingQuotes(inString)
- {
- var result = inString;
- if (inString &&
- inString.charAt(0) == '"' &&
- inString.charAt(inString.length-1) == '"'){
- result = inString.substring(1,inString.length-1);
- }
- return result;
- }
-
- // Make sure the value is there, and returns it, stripping away any enclosing quotes.
- //
- function my_GetValueForFlag(arg_num, the_flag)
- {
- if (!this.inArgs[arg_num]){
- this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_UNDEFINED_VALUE_FOR_FLAG + the_flag));
- }
- return this.StripAnyEnclosingQuotes(this.inArgs[arg_num]);
- }
-
- // Parse the parameter.
- // Return the number of arguments used in parsing the parameter.
- function my_ParseParamStartingAt(arg_num)
- {
- if (!this.inArgs[arg_num]){
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_TRIED_TO_PARSE_UNDEFINED);
- }
-
- var num_args_parsed = 0;
-
- // Check for a valid flag:
- var my_flag = this.inArgs[arg_num];
- if (my_flag == "-port"){
- // -port is used by aerender to specify a port address for a socket.
- //
- // Note: this value is sought/parsed earlier, in the SetupDefaultLog method.
- // We can just ignore here.
- var dummy = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-project"){
- this.in_project_path = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-comp") {
- this.in_comp_name = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-RStemplate") {
- this.in_RStemplate = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-OMtemplate") {
- this.in_OMtemplate = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-output") {
- this.in_output_path = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-log") {
- this.in_logfile_path = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-s") {
- this.in_start_frame = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-e") {
- this.in_end_frame = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-mem_usage") {
- this.in_image_cache_percent = this.GetValueForFlag(arg_num+1,my_flag);
- this.in_max_mem_percent = this.GetValueForFlag(arg_num+2,my_flag);
- num_args_parsed = 3;
- }
- if (my_flag == "-v") {
- this.in_verbose_flag = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-close") {
- this.in_close_flag = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-sound") {
- this.in_sound_flag = this.GetValueForFlag(arg_num+1,my_flag);
- num_args_parsed = 2;
- }
- if (my_flag == "-doSavePrefsOnQuit") {
- // The effect of this flag will be taken into account when we
- // exit the app. See comment in the "finally" block.
- // All we do here is increment the num_args_parsed count.
- num_args_parsed = 1;
- }
-
- if (num_args_parsed == 0) {
- this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, (this.MSG_BAD_FLAG + my_flag));
- }
-
- return num_args_parsed;
- }
-
- // This parses the inArgs array. Assumes
- // the array has already been filled.
- function my_ParseInArgs()
- {
- // First, undefine all the inputs we're potentially looking for
- this.in_project_path = null;
- this.in_comp_name = null;
- this.in_RStemplate = null;
- this.in_OMtemplate = null;
- this.in_output_path = null;
- this.in_logfile_path = null;
- this.in_start_frame = null;
- this.in_end_frame = null;
- this.in_image_cache_percent = null;
- this.in_max_mem_percent = null;
- this.in_verbose_flag = null;
- this.in_close_flag = null;
- this.in_sound_flag = null;
-
- // Special case: check if any argument is "-help"
- for (var i = 0; i < this.inArgs.length; i++){
- if (this.inArgs[i] == "-help"){
- this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);
- }
- }
-
- var arg_num = 0;
- while( arg_num < this.inArgs.length ){
- // ParseParamStartingAt returns the number of arguments used up parsing the param.
- arg_num += this.ParseParamStartingAt(arg_num);
- }
- }
-
- // This arg is treated differently than others because it's extra important
- // that we exit properly in the face of anything that might go wrong even
- // during initialization. So we don't parse the standard way, we check this
- // before exit...
- function my_IsSavePrefsArgGiven(arglist)
- {
- return this.IsInArray("-doSavePrefsOnQuit", arglist);
- }
-
- // Returns true if the item equals an item in the array, false if otherwise.
- function my_IsInArray(needle, haystack)
- {
- result = false;
- for (var i = 0; i < haystack.length; i++){
- if (needle == haystack[i]){
- result = true;
- break;
- }
- }
- return result;
- }
-
- function my_SetupDefaultLog(arg_list)
- {
- this.has_user_log_file = false;
-
- // Clean up after a potentially bad exit last time:
- if (this.log_file && this.log_file != null){
- this.log_file.close();
- this.log_file = null;
- }
-
- // Open the socket.
- // It is used:
- // [a] to log errors if there is no user-specified log file (specified with a "-log" arg)
- // [b] to log errors encountered while opening any user-specified log file.
-
- // See if a -port argument was passed:
- this.log_file = null;
- for (var i = 0; i < arg_list.length; i++){
- if (arg_list[i] == "-port"){
- if (arg_list.length > i+1){
- // The argument value is the port address
- this.in_port_address = arg_list[i+1];
- // Yes, the log_file variable is being used to hold a socket.
- this.log_file = new Socket();
- if ( !this.log_file.open(this.in_port_address,"binary") ) {
- this.log_file = null;
- this.SetExitCodeAndThrowException(this.EXIT_CANNOT_OPEN_SOCKET,
- this.MSG_CAN_NOT_OPEN_SOCKET);
- }
- }
- }
- }
- this.is_verbose_mode = true;
- }
-
- function my_CleanupDefaultLog()
- {
- // Close the log file
- if (this.log_file != null){
- this.log_file.close();
- this.log_file = null;
- }
- }
-
- // This is the external entry point.
- // Bat files or executables may call this method.
- //
- // This function assumes that it has been passed all the arguments.
- // It parses the arguments and then renders.
- function my_Render()
- {
- app.beginSuppressDialogs();
- try {
- this.SetupDefaultLog(my_Render.arguments);
-
- // start by assuming successful execution, exit code 0.
- app.exitCode = 0;
-
- // Check number of arguments
- if (!my_Render.arguments || my_Render.arguments.length == 0){
- this.SetExitCodeAndThrowException(this.EXIT_SHOW_USAGE, this.MSG_SHOW_USAGE);
- }
-
- var numArgs = my_Render.arguments.length ;
- // Allocate the array of arguments:
- this.inArgs = new Array(numArgs);
-
- // Load the input arguments into the inArgs array.
- for (var i = 0; i < numArgs; i++) {
- this.inArgs[i] = my_Render.arguments[i];
- }
-
- // Parse the arguments, and render
- this.ParseInArgs();
- this.ReallyRender();
-
- } catch(error) {
- // Add any errors to the log file.
- if (this.log_file != null){
- this.log_file.writeln(error.toString());
- }
- this.SetExitCode(this.EXIT_AE_RUNTIME);
- }
-
- finally {
- // This arg is treated differently than others because it's extra important
- // that we exit properly in the face of anything that might go wrong even
- // during initialization. So we don't parse the standard way, we check this
- // before exit...
- app.setSavePreferencesOnQuit(this.IsSavePrefsArgGiven(my_Render.arguments));
-
- this.CleanupDefaultLog();
- app.endSuppressDialogs(false);
- }
- }
-
- function my_ReallyRender()
- {
- this.saved_sound_setting = null;
-
- try {
- // While rendering we'll report errors to the log file.
- if (app.onError == this.onError){
- // If the previous error handler is just this one, don't store it.
- // That can happen in extreme cases where this script does not get a
- // chance to clean up and put back the oldErrorHandler when it's done.
- this.oldErrorHandler = null;
- } else {
- this.oldErrorHandler = app.onError;
- }
- app.onError = this.onError;
- // Open the user log file, if specified, and use it instead of the socket.
- if (this.in_logfile_path) {
- // Keep the socket open; errors we encounter while opening the
- // user log file will be logged to the socket.
- var user_log_file = new File(this.in_logfile_path);
- var parent_dir = user_log_file.parent;
- if (!parent_dir.exists){
- if (this.log_file){
- this.log_file.writeln(this.MSG_LOG_DIR_NO_EXISTS + this.in_logfile_path);
- }
- this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
- }
- var test_folder = Folder(parent_dir);
- if (!(test_folder instanceof Folder)){
- if (this.log_file){
- this.log_file.writeln(this.MSG_LOG_DIR_NOT_A_DIR + this.in_logfile_path);
- }
- this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
- }
- if (!user_log_file.open("w",'TEXT','ttxt')){
- if (this.log_file){
- this.log_file.writeln(this.MSG_LOG_CAN_NOT_OPEN + this.in_logfile_path);
- }
- this.SetExitCodeAndThrowException(this.EXIT_AE_RUNTIME, this.MSG_AE_RUNTIME);
- }
-
- // no errors were encountered opening the file.
- // Close the socket and use this one instead.
- if (this.log_file != null){
- this.log_file.close();
- }
- this.log_file = user_log_file; // which is still open
- this.has_user_log_file = true;
- }
-
- if (this.in_verbose_flag){
- if (this.in_verbose_flag == "ERRORS"){
- this.is_verbose_mode = false;
- } else if (this.in_verbose_flag == "ERRORS_AND_PROGRESS") {
- this.is_verbose_mode = true;
- } else {
- this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_VERBOSE_FLAG);
- }
- }
- if (this.in_close_flag){
- if (this.in_close_flag != "DO_NOT_CLOSE" &&
- this.in_close_flag != "DO_NOT_SAVE_CHANGES" &&
- this.in_close_flag != "SAVE_CHANGES"){
- this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_CLOSE_FLAG);
- }
- }
- if (this.in_sound_flag){
- if (this.in_sound_flag != "ON" &&
- this.in_sound_flag != "OFF" &&
- this.in_sound_flag != "on" &&
- this.in_sound_flag != "off"){
- this.SetExitCodeAndThrowException(this.EXIT_SYNTAX_ERROR, this.MSG_BAD_SOUND_FLAG);
- }
- }
-
- // Set the memory usage, if specified as an argument.
- if (this.in_image_cache_percent && this.in_max_mem_percent){
- app.setMemoryUsageLimits(this.in_image_cache_percent, this.in_max_mem_percent);
- }
-
- // If the user provided a project, close the current project and open the project specified.
- // Else, leave the current project open.
- if (this.in_project_path){
- // Close the current project
- if (app.project != null){
- app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
- }
-
- // Open the specified project:
- var proj_file = new File(this.in_project_path);
- app.open(proj_file);
- }
- if (!app.project){
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NO_PROJECT);
- }
-
- // Get the RenderQueueItem for the specified comp, if specified.
- var rqi = null;
- if (this.in_comp_name){
- rqi = this.GetFirstQueueableRQItemWithName(this.in_comp_name);
- }
- if (this.in_comp_name && !rqi) {
- // Try to find the comp in the project and add to the render queue:
- rqi = this.AddCompToRenderQueue(this.in_comp_name);
- if (rqi){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_ADDING_TO_RQ);
- }
- } else {
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_COMP_NOT_FOUND);
- }
- }
-
- // Apply the templates, if provided
- if (this.in_RStemplate){
- if (!this.in_comp_name){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_NO_COMP_YES_TEMPLATE);
- }
- } else {
- if (!this.IsInArray(this.in_RStemplate, rqi.templates)) {
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_RS_TEMPLATE_NOT_FOUND);
- }
- rqi.applyTemplate(this.in_RStemplate);
- }
- }
- if (this.in_OMtemplate){
- if (!this.in_comp_name){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_NO_COMP_YES_OMTEMPLATE);
- }
- } else {
- if (!this.IsInArray(this.in_OMtemplate, rqi.outputModule(1).templates)) {
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_OM_TEMPLATE_NOT_FOUND);
- }
- rqi.outputModule(1).applyTemplate(this.in_OMtemplate);
- }
- }
-
- // If a comp was specified, make it the only one to render.
- // If none was provided, leave everything alone so render queue renders as is.
- if (this.in_comp_name) {
- this.EstablishAsOnlyQueuedItem(rqi);
- }
-
- if (this.in_comp_name){
- // If the user provided a path, set the output path on rqi's OutputModule
- if (rqi.status == RQItemStatus.NEEDS_OUTPUT && !this.in_output_path){
- this.SetExitCodeAndThrowException(this.EXIT_AERENDER_RUNTIME, this.MSG_NEEDS_OUTPUT);
- }
- if (this.in_output_path){
- var om = rqi.outputModule(1);
- om.file = new File(this.in_output_path);
- }
- } else {
- if (this.in_output_path){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_NO_COMP_YES_OUTPUT);
- }
- }
- }
-
- // Set the start and end frames.
- if (this.in_start_frame || this.in_end_frame) {
- if (!this.in_comp_name){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_NO_COMP_YES_START_OR_END);
- }
- }
- else {
- // Render times are stored as timeSpanStart and timeSpanDuration.
- // Setting only the timeSpanStart will not change the timeSpanDuration and
- // so will move the end time, but we want the end time unchanged if
- // it was not specified.
- // So we must calculate both start_time and end_time,
- // then set both timeSpanStart and timeSpanDuration.
- // Note: frameDuration is stored in the comp.
- var start_time = rqi.timeSpanStart;
- var end_time = rqi.timeSpanStart + rqi.timeSpanDuration;
- if (this.in_start_frame){
- start_time = this.in_start_frame * rqi.comp.frameDuration;
- }
- if (this.in_end_frame){
- // The way AE works, final frame is not included.
- // But aerender wants final frame included.
- // So, just add 1 to end frame right here before setting
- // duration for AE:
- // Note: must call parseInt() here, or the 1 will be added as if it
- // were a string. For example, 35 would become 351, not 36. Hoo boy!
- var end_frame_plus_one = parseInt(this.in_end_frame,10) + 1.0;
- end_time = end_frame_plus_one * rqi.comp.frameDuration;
- }
- rqi.timeSpanStart = start_time;
- rqi.timeSpanDuration = end_time - start_time;
- }
- }
-
- // If we are in verbose mode, set the log type to ERRORS_AND_PER_FRAME_INFO
- // for all RQ items we are about to render.
- if (this.is_verbose_mode){
- this.SetLogPerFrameInfoInRQ();
- }
-
- this.SaveAndSetRenderSoundSetting();
-
- // Render!
- app.project.renderQueue.render();
-
- } catch(error) {
- // Add any errors to the log file.
- if (this.log_file != null){
- this.log_file.writeln(error.toString());
- }
-
- // It's possible that errors were encountered while trying to render.
- // Stop the render if in progress for a clean exit from the application.
- if (app.project && app.project.renderQueue && app.project.renderQueue.rendering){
- // This will prevent the message "render stopped by user" from showing up...
- app.onError = null;
- app.project.renderQueue.stopRendering();
- // This will print a better message:
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_RENDER_ABORTED);
- }
- app.onError = this.onError;
- }
-
- this.SetExitCode(this.EXIT_AE_RUNTIME);
- }
-
- finally {
-
- // Close the project.
- this.CloseProjectIfDesired();
-
- // Put back the old error handler
- app.onError = this.oldErrorHandler;
-
- // Restore the setting for hearing the render-done sound.
- this.RestoreRenderSoundSetting()
- }
- }
-
- // Returns the first item on the render queue that:
- // [a] contains a comp named comp_name
- // [b] has a render status of QUEUED or UNQUEUED or NEEDS_OUTPUT
- // Note that if the status is NEEDS_OUTPUT, one better be provided or
- // an error will result.
- //
- // If not found, returns null.
- //
- function my_GetFirstQueueableRQItemWithName(comp_name)
- {
- var result = null;
-
- var rq = app.project.renderQueue;
- if (rq && rq.numItems > 0){
- var cur_item;
- // the items are indexed from 1 to numItems.
- for (var i = 1; i <= rq.numItems; i++){
- cur_item = rq.item(i);
- if (cur_item.comp.name == comp_name &&
- cur_item.status == RQItemStatus.WILL_CONTINUE){
- if (this.log_file != null){
- this.log_file.writeln(this.MSG_SKIPPING_WILL_CONTINUE);
- }
- }
- if (cur_item.comp.name == comp_name &&
- (cur_item.status == RQItemStatus.QUEUED ||
- cur_item.status == RQItemStatus.UNQUEUED ||
- cur_item.status == RQItemStatus.NEEDS_OUTPUT)){
- // We found it!
- result = cur_item;
- break;
- }
- }
- }
-
- return result;
- }
-
- // Find a comp with the given name, and adds it to the render queue.
- // Returns the newly added render queue item
- //
- // If not found, returns null.
- //
- function my_AddCompToRenderQueue(comp_name)
- {
- var result = null;
-
- // Get the comp with the name we are after
- var cur_item;
- var desired_comp = null;
- // the items in the project are indexed from 1 to numItems
- for (var i = 1; i <= app.project.numItems; i++){
- cur_item = app.project.item(i);
- if (cur_item instanceof CompItem && cur_item.name == comp_name){
- desired_comp = cur_item;
- break;
- }
- }
-
- // Add the desired_comp to the render queue. The add() method
- // returns the new render queue item.
- if (desired_comp){
- result = app.project.renderQueue.items.add(desired_comp);
- }
-
- return result;
- }
-
- // Sets the render flag on all RenderQueueItems other than rqi to false,
- //
- function my_EstablishAsOnlyQueuedItem(rqi)
- {
- var rq = app.project.renderQueue;
- if (rq && rq.numItems > 0){
- var cur_item;
- // the items are indexed from 1 to numItems.
- for (var i = 1; i <= rq.numItems; i++){
- cur_item = rq.item(i);
- if (cur_item == rqi) {
- cur_item.render = true;
- } else {
- // You can only change the render flag when these are the current status value:
- if (cur_item.status == RQItemStatus.QUEUED ||
- cur_item.status == RQItemStatus.UNQUEUED ||
- cur_item.status == RQItemStatus.NEEDS_OUTPUT ||
- cur_item.status == RQItemStatus.WILL_CONTINUE){
- cur_item.render = false;
- }
- }
- }
- }
- }
-
- // Sets the log type to be ERRORS_AND_PER_FRAME_INFO for all items that are going to render.
- //
- function my_SetLogPerFrameInfoInRQ()
- {
- var rq = app.project.renderQueue;
- if (rq && rq.numItems > 0){
- var cur_item;
- // the items are indexed from 1 to numItems.
- for (var i = 1; i <= rq.numItems; i++){
- cur_item = rq.item(i);
- if (cur_item.render == true){
- if (cur_item.status != RQItemStatus.USER_STOPPED &&
- cur_item.status != RQItemStatus.ERR_STOPPED &&
- cur_item.status != RQItemStatus.RENDERING &&
- cur_item.status != RQItemStatus.DONE) {
- cur_item.logType = LogType.ERRORS_AND_PER_FRAME_INFO;
- }
- }
- }
- }
- }
-
- // Closes the project if the close flag specifies to do so
- //
- function my_CloseProjectIfDesired()
- {
- if (app.project) {
- // Close the project we just used, if desired
- if (!this.in_close_flag || this.in_close_flag == "DO_NOT_SAVE_CHANGES"){
- // If no flag provided, this is the default.
- app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
- } else {
- if (this.in_close_flag == "SAVE_CHANGES"){
- app.project.close(CloseOptions.SAVE_CHANGES);
- }
- // otherwise, flag is DO_NOT_CLOSE, so we do nothing.
- }
- }
- }
-
- function my_SaveAndSetRenderSoundSetting()
- {
- // Save the current setting for hearing the render-done sound, we'll restore it later.
- if (app.preferences.havePref("Misc Section",
- "Play sound when render finishes") ){
- // Get the current value if the pref exists.
- this.saved_sound_setting = app.preferences.getPrefAsLong("Misc Section",
- "Play sound when render finishes");
- } else {
- // default is to play the sound, value of 1.
- // Use this if the pref does not yet exist.
- this.saved_sound_setting = 1;
- }
-
- // Set the setting for hearing the render-done sound, based on the input, default is off.
- this.my_sound_setting = 0; // 0 is off
- if (this.in_sound_flag && (this.in_sound_flag == "ON" || this.in_sound_flag == "on")){
- this.my_sound_setting = 1; // 1 is on
- }
-
- app.preferences.savePrefAsLong("Misc Section",
- "Play sound when render finishes",
- this.my_sound_setting);
- }
-
- function my_RestoreRenderSoundSetting()
- {
- if (this.saved_sound_setting){
- app.preferences.savePrefAsLong("Misc Section",
- "Play sound when render finishes",
- this.saved_sound_setting);
- }
- }
-
- // [3] assign all the functions to be method-type attributes.
- //
- this.onError = my_onError;
- this.SetExitCodeAndThrowException = my_SetExitCodeAndThrowException;
- this.SetExitCode = my_SetExitCode;
- this.StripAnyEnclosingQuotes = my_StripAnyEnclosingQuotes;
- this.GetValueForFlag = my_GetValueForFlag;
- this.ParseParamStartingAt = my_ParseParamStartingAt;
- this.ParseInArgs = my_ParseInArgs;
- this.IsInArray = my_IsInArray;
- this.SetupDefaultLog = my_SetupDefaultLog;
- this.CleanupDefaultLog = my_CleanupDefaultLog;
- this.Render = my_Render;
- this.ReallyRender = my_ReallyRender;
- this.GetFirstQueueableRQItemWithName = my_GetFirstQueueableRQItemWithName;
- this.AddCompToRenderQueue = my_AddCompToRenderQueue;
- this.EstablishAsOnlyQueuedItem = my_EstablishAsOnlyQueuedItem;
- this.SetLogPerFrameInfoInRQ = my_SetLogPerFrameInfoInRQ;
- this.CloseProjectIfDesired = my_CloseProjectIfDesired;
- this.SaveAndSetRenderSoundSetting = my_SaveAndSetRenderSoundSetting;
- this.RestoreRenderSoundSetting = my_RestoreRenderSoundSetting;
- this.IsSavePrefsArgGiven = my_IsSavePrefsArgGiven;
- }
-
- var gAECommandLineRenderer = new AECommandLineRenderer();
-
-
-